/**
 * 用户配置
 */
<template>
    <vp-dialog ref="editDialogRef" :span="1">
        <template #title>
            <vp-label zh="用户配置" en="User Config" align="left"/>
        </template>
		<vp-card shadow="hover" class="mb5">
            <el-form label-suffix=":"  ref="searchFormRef" :model="searchForm" @submit.prevent
            @keyup.enter="handleSearch" label-width="120px">
                <vp-search-row >
                    <vp-search-col :span="2">
                        <el-form-item prop="keyword">
                            <template #label><vp-label-keyword/></template>
                            <el-input v-model="searchForm.keyword" v-trim placeholder=""></el-input>
                        </el-form-item>
                    </vp-search-col>
                    <vp-search-col :span="2" v-if="isMultiDepartments">
                        <el-form-item :label-width="120">
							<el-checkbox v-model="searchForm.jgbs" :true-value="1" :false-value="0">
								<vp-label zh="可选择其它租户的用户" en="Selection Of Other Tenants"/>
							</el-checkbox>
						</el-form-item>
                    </vp-search-col>
                    <vp-search-col btn-col>
                        <vp-btn-search :loading="loading" @click="handleSearch"/>
                        <vp-btn-reset @click="handleSearchReset"/>
                    </vp-search-col>
                </vp-search-row>
            </el-form>
		</vp-card>
      <el-row>
        <vp-col :span="1">
          <vp-card shadow="hover" v-loading="loading" class="department-tree">
            <span class="custom-tree-label">
							<span>按部门/By Department</span>
						</span>
            <el-scrollbar height="calc(100vh - 500px)">
              <el-tree 
                :key="nodeKey"
                node-key="treeId"
                show-checkbox
                ref="departmentTreeRef"
                :data="processDepartmentData" 
                :default-checked-keys="defaultCheckedKeys4Department"
                :props="defaultProps" 
                :default-expand-all="true"
                :expand-on-click-node="false"
                :check-on-click-node="true"
                @check="handleCheckChangeByDepartment">
                <template #default="{ node, data }">
                  <el-icon v-if="data.type === 1"><ele-OfficeBuilding /></el-icon>
                  <el-icon v-if="data.type === 2"><ele-Avatar /> </el-icon>
                  <span class="pl8">
                    <span v-html="markTextColor(searchForm.keyword, node.label)" />
                  </span>
                </template>
              </el-tree>
            </el-scrollbar>
          </vp-card>
        </vp-col>
      </el-row>
      <el-row>
        <span class="custom-tree-label" style="min-height: 32px;padding-top: 5px;">已选人员/Checked Person：</span>
        <el-tag
          v-for="tag in checkedPerson"
          :key="tag.id"
          class="ml5 mr5"
          closable
          type="success"
          effect="dark"
          @close="handleCloseTag(tag)"
        >
          {{ tag.label }}
        </el-tag>
      </el-row>
		<template #footer>
      <vp-btn-confirm :loading="saveLoading"  @click="handleSave"/>
		</template>
  </vp-dialog>
</template>
<script setup lang="ts" name="editRoleUser">
import { computed, defineComponent, nextTick, reactive, ref, toRefs } from 'vue';
import request from '/@/utils/request';
import { markTextColor } from "/@/utils/toolsValidate";
import { useUserInfo } from '/@/stores/userInfo';

const emits = defineEmits(['formSubmited']);

interface UserTreeNode {
    id: string;
    treeId: string;
    label: string;
    type: 1 | 2;
    bmdm?: string;
    children?: UserTreeNode[];
}

const stores = useUserInfo();
const userInfos = stores.userInfos;
const isMultiDepartments = computed(() => {
    return userInfos.departments && userInfos.departments.length > 0 && userInfos.departments[0].children && userInfos.departments[0].children.length > 0;
});

const searchForm = ref({
    keyword: "",
    jgbs: 0,
});

const roleId = ref('');
const users = ref([]);
const allUsers = ref([]);
const departments = ref([] as any[]);
const loading = ref(false);
const saveLoading = ref(false);
const defaultProps = ref({
    children: 'children',
    label: 'label',
});
const nodeKey = ref("key");
const defaultSelected = ref([]);
const currentSelected = ref([]);

const editDialogRef = ref();
const searchFormRef = ref();
const departmentTreeRef = ref();
const type = ref(1);

const handleOpen = (param: any) => {
    editDialogRef.value.handleOpen();
    roleId.value = param.id;
    type.value = param.type || 1;
    loading.value = true;
    if (type.value === 1) {
        request.get(`/system/role/user/${param.id}`).then((res)=>{
            const selected = (res.data || []).filter((user: any) => { 
                return user.flag === 1;
            }).map((user: any) => {
                return user.id;
            });
            defaultSelected.value = selected;
            currentSelected.value = [...defaultSelected.value];
            loading.value = false;
            loadDataList();
        })
    } else if (type.value === 2) {
        request.get(`/system/user/warehouse/queryByCkid/${param.id}`).then((res)=>{
            const selected = (res.data || []).map((user: any) => {
                return user.id;
            });
            defaultSelected.value = selected;
            currentSelected.value = [...defaultSelected.value];
            loading.value = false;
            loadDataList();
        })
    } else if (type.value === 3) {
        request.get(`/system/user/base/queryByJdid/${param.id}`).then((res)=>{
            const selected = (res.data || []).map((user: any) => {
                return user.id;
            });
            defaultSelected.value = selected;
            currentSelected.value = [...defaultSelected.value];
            loading.value = false;
            loadDataList();
        })
    } else if (type.value === 4) {
        request.get(`/system/modelRole/user/${param.id}`).then((res)=>{
            const selected = (res.data || []).map((user: any) => {
                return user.yhid;
            });
            defaultSelected.value = selected;
            currentSelected.value = [...defaultSelected.value];
            loading.value = false;
            loadDataList();
        })
    }
}

const loadDataList = () => {
    loading.value = true;
    request.get('/system/user/tree/list',{
        params: {
            type: 1,
            jgbs: 1
        }
    }).then(res => {
        allUsers.value = res?.data?.users || [];
        allUsers.value.forEach((user: any) => {
            user.treeId = user.id;
            user.label = user.zh + ' ' + user.xm;
            user.type = 2;
        });
        departments.value = filterDepartments(res?.data?.departments || []);
        nodeKey.value = new Date().getTime() + "";
        setCurrentUsers();
    }).finally(() => {
        loading.value = false
    })
}

const handleSave = () => {
    if (loading.value) {
        return;
    }
    let url = '';
    if (type.value === 1) {
        url = `/system/role/user/${roleId.value}`;
    } else if (type.value === 2) {
        url = `/system/user/warehouse/saveByCkid/${roleId.value}`;
    } else if (type.value === 3) {
        url = `/system/user/base/saveByJdid/${roleId.value}`;
    } else if (type.value === 4) {
        url = `/system/modelRole/user/${roleId.value}`;
    }
    const idList = checkedPerson.value.map((user: any) => { return user.yhid });
    saveLoading.value = true;
    request.post(url, idList).then(()=>{
        saveLoading.value = false;
        emits("formSubmited");
        editDialogRef.value.handleClose();
    })
    
}

const handleSearch = () => {
    loadDataList();
}


const handleSearchReset = () => {
    searchFormRef.value.resetFields();
    searchForm.value.keyword = '';
}

const processDepartmentData = computed(() => {
    let treeList = assessmentDepartmentList(departments.value);
    treeList.push({
        id: '-99',
        treeId: '-99',
        label: '无部门人员',
        type: 1,
        children: users.value.filter((user: any)=>{return !user.bmdm;})
    });
    return treeList;
})

const assessmentDepartmentList = (list: any[])=> {
    let treeList = [] as UserTreeNode[];
    (list||[]).forEach((department: any)=>{
        const users_temp = users.value.map((user: any)=>{
            return {...user};
        }).filter((user: any)=>{
            return user.bmdm === department.id;
        });
        treeList.push({
            id: department.id,
            treeId: department.id,
            label: department.dprtname,
            type: 1,
            children: assessmentDepartmentList(department.children).concat(users_temp)
        });
    });
    return treeList;
}

const handleCheckChangeByDepartment = (data: any) => {
    const targetNode = departmentTreeRef.value.getNode(data);
    const checked = targetNode.checked;
    const allChildren = getAllChildren(targetNode);
    const uniqueKeys = getDistinctUserKeys(allChildren);
    if (checked) {
        currentSelected.value = mergeAndDistinct(currentSelected.value, uniqueKeys);
        departmentTreeRef.value.setCheckedKeys(currentSelected.value, false);
    } else {
        currentSelected.value = reduceAndDistinct(currentSelected.value, uniqueKeys);
        departmentTreeRef.value.setCheckedKeys(currentSelected.value, false);
    }
}

/**
 * 过滤出用户节点并去重
 */
const getDistinctUserNodes = (nodes) => {
    const filterNodes = nodes.filter((node) => { return node.type === 2})
    const uniqueNodes = filterNodes.filter((node, index) => filterNodes.findIndex((n) => { return n.id === node.id}) === index);
    return uniqueNodes;
}

/**
 * 过滤出用户key并去重
 */
const getDistinctUserKeys = (nodes) => {
    const uniqueNodes = getDistinctUserNodes(nodes);
    const uniqueKeys = uniqueNodes.map((node) => { return node.id});
    return uniqueKeys;
}

/**
 * 获取tree某个节点下的所有子节点
 */
const getAllChildren = (node, allChildren = [node.data]) => {
    if (node.childNodes && node.childNodes.length) {
        node.childNodes.forEach(child => {
        allChildren.push(child.data);
        getAllChildren(child, allChildren);
        });
    }
    return allChildren;
}

/**
 * 合并&去重数组
 */
const mergeAndDistinct = (arr1, arr2) => {
    let merged = arr1.concat(arr2);
    let distinct = Array.from(new Set(merged));
    return distinct;
}

/**
 * 缩减&去重数组
 */
const reduceAndDistinct = (arr1, arr2) => {
    let merged = arr1.filter((obj1) => {return !arr2.some((obj2) => {return obj1 === obj2})});
    let distinct = Array.from(new Set(merged));
    return distinct;
}

const checkedPerson = computed(() => {
    return currentSelected.value.map((obj: any) => {
        return allUsers.value.find((user: any) => {return user.id === obj || user.daid === obj}) || {} as any;
    });
})

const handleCloseTag = (tag: any) => {
    if(tag.id){
        departmentTreeRef.value.setChecked(tag.id, false, false);
        currentSelected.value = currentSelected.value.filter((obj: any) => {return obj !== tag.id});
    }else{
        currentSelected.value = currentSelected.value.filter(id => 
            allUsers.value.some(user => user.id === id)
        );
    }
}

const defaultCheckedKeys4Department = computed(() => {
    let checkedKeys = [] as string[];
    users.value.forEach((user: any) => {
        if ((defaultSelected.value).includes(user.yhid) || (defaultSelected.value).includes(user.daid)) {
        checkedKeys.push(user.id);
        }
    });
    return checkedKeys;
})

const setCurrentUsers = () => {
    users.value = allUsers.value.filter((user: any) => {
        let flag = true;
        if (searchForm.value.keyword) {
            if (!((user.zh && user.zh.toUpperCase().indexOf(searchForm.value.keyword.toUpperCase()) > -1) ||
                    (user.xm && user.xm.toUpperCase().indexOf(searchForm.value.keyword.toUpperCase()) > -1) ||
                    (user.abbr && user.abbr.toUpperCase().indexOf(searchForm.value.keyword.toUpperCase()) > -1) ||
                    (user.pinyin && user.pinyin.toUpperCase().indexOf(searchForm.value.keyword.toUpperCase()) > -1))) {
                flag = false;
            }
        }
        if (searchForm.value.jgbs === 0) {
            if (user.jgdm !== userInfos.user.jgdm) {
                flag = false;
            }
        }
        return flag;
    });
}

const filterDepartments = (departments: any[]) => {
    if (searchForm.value.jgbs === 0) {
        const targetDepartments = [] as any[];
        findTargetDepartment(departments, userInfos.user.jgdm, targetDepartments);
        return targetDepartments;
    }
    return departments;
}

const findTargetDepartment = (departments: any[], jgdm: string, targetDepartments: any[]) => {
    departments.forEach((department: any) => {
        if (department.dprtcode === jgdm) {
            targetDepartments.push(department);
        } else {
            findTargetDepartment(department.children || [], jgdm, targetDepartments);
        }
    });
}

defineExpose({
    handleOpen,
})

</script>
<style scoped lang="scss">
	.custom-tree-label {
		display: flex;
		align-items: center;
		justify-content: space-between;
		font-size: 14px;
		font-weight: bold;
		padding: 0 8px 8px 10px;
	}
</style>